#include<stdio.h>
#include<Arcroll.h>
#include<Mesh_IO/Mesh_IO.h>
#include<Mesh/libcell_iterator.h>
#include<libcell_macros.h>


#define Matrix4x4 LB_Matrix

#include<nfd.h>



typedef struct SFM_struct{
    char* in_file_dir;
    char* out_dir;
    Mesh * mesh;
    Viewer_Opengl_Interpreter* voi;
    Viewer_World* vw;

    void* prop;
}SFM_struct;


static inline void sfm_strutct_init(SFM_struct* sfm_s)
{
    sfm_s->in_file_dir=NULL;
    sfm_s->out_dir=NULL;
    sfm_s->mesh=(Mesh*)malloc(sizeof(Mesh));
    Mesh_init(sfm_s->mesh);
    sfm_s->voi=NULL;
    sfm_s->vw=NULL;

    sfm_s->prop=NULL;
}
static inline void  sfm_strutct_free(SFM_struct*sfm_s)
{
    SAFE_FREE(sfm_s->in_file_dir);
    SAFE_FREE(sfm_s->out_dir);
    Mesh_free(sfm_s->mesh);

}

char* test2();


void test_show_mesh_points(Viewer_World* vw,Mesh* m)
{
    Node* n=vw->create_something(vw,"Points");
    Viewer_Something*vs=(Viewer_Something*)(n->value);
    Viewer_Points* vp=(Viewer_Points*)(vs->evolution);
    vp->Data_rows=m->num_v(m);
    //vp->Data_rows=40000;
    vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    vp->color=(float*)malloc(sizeof(float)*4*vp->Data_rows);

    //vp->set_color(vp,1,0,0,1.0);
    int i=0;
    for(auto vit=m->v_begin(m);vit!=m->v_end(m);vit++)
    {
        //printf("%lf %lf %lf\n",quote(vit)->point[0],quote(vit)->point[1],quote(vit)->point[2]);

        vp->Data[i*3+0]=quote(vit)->point[0];vp->Data[i*3+1]=quote(vit)->point[1];vp->Data[i*3+2]=quote(vit)->point[2];
        PLY_Vertex_Prop* pvp=(PLY_Vertex_Prop*)(quote(vit)->prop);
        vp->color[i*4+0]=pvp->rgb[0]/255.0;vp->color[i*4+1]=pvp->rgb[1]/255.0;
        vp->color[i*4+2]=pvp->rgb[2]/255.0;vp->color[i*4+3]=1.0;


        //printf("%d \n",pvp->rgb[0]); 
        i++;
        // if(i>=vp->Data_rows)
        // {
        //     break;

        // }
    }

    free_node(n); 
}


void test_ui_callback(Viewer_Intera* vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;
    Interactor_PickInfo ipi=g_info->ipi;
    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        //printf("shi\n");
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;

        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
        vum->change_color=1.0;   
    }
}

void select_image_call_fun(Viewer_Intera*vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;
    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);
    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        //printf("shi\n");
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            SAFE_FREE(sfm_s->in_file_dir); 
            sfm_s->in_file_dir= test2();
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
        vum->change_color=1.0;   
    }
}

void select_out_dir_call_fun(Viewer_Intera*vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;
    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);
    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        //printf("shi\n");
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            SAFE_FREE(sfm_s->out_dir); 
            sfm_s->out_dir= test2();
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
        vum->change_color=1.0;   
    }
}
void compute_feature_call_fun(Viewer_Intera* vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;  

    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);


    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        // printf("shi\n");
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            if(sfm_s->in_file_dir==NULL||sfm_s->out_dir==NULL)
            {
                printf("请选择图片目录和输出目录\n");

            } 
            else
            {
                char command[500]={0};
                strcat(command,"python pythontest.py ");
                strcat(command,sfm_s->in_file_dir);
                strcat(command,"  ");
                strcat(command,sfm_s->out_dir);
                strcat(command," 1"); 
                printf("command:%s\n",command); 
                system(command); 

            }
            //vs->update=1;
            //printf("shiqule vum\n");
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
            vum->change_color=1.0;   
    }
}
void compute_match_call_fun(Viewer_Intera* vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;  

    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);

    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        // printf("shi\n");
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            if(sfm_s->in_file_dir==NULL||sfm_s->out_dir==NULL)
            {
                printf("请选择图片目录和输出目录\n");

            } 
            else
            {
                char command[500]={0};
                strcat(command,"python pythontest.py ");
                strcat(command,sfm_s->in_file_dir);
                strcat(command,"  ");
                strcat(command,sfm_s->out_dir);
                strcat(command," 2"); 
                printf("command:%s\n",command); 
                system(command); 
            }
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
            vum->change_color=1.0;   
    }
}

void compute_sfm_call_fun(Viewer_Intera* vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;  

    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);

    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        // printf("shi\n");
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            if(sfm_s->in_file_dir==NULL||sfm_s->out_dir==NULL)
            {
                printf("请选择图片目录和输出目录\n");

            } 
            else
            {
                char command[500]={0};
                strcat(command,"python pythontest.py ");
                strcat(command,sfm_s->in_file_dir);
                strcat(command,"  ");
                strcat(command,sfm_s->out_dir);
                strcat(command," 3"); 
                printf("command:%s\n",command); 
                system(command); 
            }
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
            vum->change_color=1.0;   
    }
}

void compute_densify_cloud_call_fun(Viewer_Intera* vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;  

    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);

    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            if(sfm_s->in_file_dir==NULL||sfm_s->out_dir==NULL)
            {
                printf("请选择图片目录和输出目录\n");
            } 
            else
            {
                char command[500]={0};
                strcat(command,"python pythontest.py ");
                strcat(command,sfm_s->in_file_dir);
                strcat(command,"  ");
                strcat(command,sfm_s->out_dir);
                strcat(command," 4"); 
                printf("command:%s\n",command); 
                system(command); 

                if(sfm_s->mesh->num_v(sfm_s->mesh)==0)
                {
                    _ReadPly_(sfm_s->mesh,"./out/dense.ply");
                }
                test_show_mesh_points(sfm_s->vw,sfm_s->mesh); 
                sfm_s->voi->update_data(sfm_s->voi);
                
                printf("end densify cloud\n");
            }
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
            vum->change_color=1.0;   
    }
}
void compute_point2mesh_key_call_fun(Viewer_Intera*vi)
{
    // Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    // Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;  

    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);

    if(g_info->key_action==VIEWER_PRESS&&g_info->key==VIEWER_KEY_P)
    {
             
            if(sfm_s->in_file_dir==NULL||sfm_s->out_dir==NULL)
            {
                printf("请选择图片目录和输出目录\n");
            } 
            else
            { 
                char command[500]={0};
                strcat(command,"python pythontest.py ");
                strcat(command,sfm_s->in_file_dir);
                strcat(command,"  ");
                strcat(command,sfm_s->out_dir);
                strcat(command," 5"); 
                printf("command:%s\n",command); 
                system(command); 
 
                system("Viewer ./out/refine_texture_mesh.mvs");
                printf("end point2mesh one  \n");          
            } 
    } 
}
void compute_point2mesh_call_fun (Viewer_Intera* vi)
{
    Viewer_UI_Mesh* vum=(Viewer_UI_Mesh*)(vi->representation);
    Viewer_Something * vs=vum->texture;
    Interactor_GlobalInfo* g_info=vi->g_info;  

    Interactor_PickInfo ipi=g_info->ipi;
    SFM_struct* sfm_s=(SFM_struct*)(vi->prop);

    if(g_info->mouse_button==VIEWER_MOUSE_BUTTON_LEFT&&g_info->mouse_action==VIEWER_PRESS)
    {
        if(ipi.vs!=NULL&&vum==ipi.vs->evolution)
        {
            vum->change_color=0.5;
            if(sfm_s->in_file_dir==NULL||sfm_s->out_dir==NULL)
            {
                printf("请选择图片目录和输出目录\n");
            } 
            else
            { 
                char command[500]={0};
                strcat(command,"python pythontest.py ");
                strcat(command,sfm_s->in_file_dir);
                strcat(command,"  ");
                strcat(command,sfm_s->out_dir);
                strcat(command," 5"); 
                printf("command:%s\n",command); 
                system(command); 
 
                system("Viewer ./out/refine_texture_mesh.mvs");
                printf("end point2mesh one  \n");
                
            }
            
        }
    } 
    else if(g_info->mouse_button==VIEWER_RELEASE)
    {
            vum->change_color=1.0;   
    }
}


void viewer_add_button(Viewer_World* vw,char * image ,float*pos , void (call_fun)(Viewer_Intera*),void* prop )
{
    char uimesh[]="UI_Mesh";
    Node* n=vw->create_something(vw,uimesh);
    auto vs=(Viewer_Something*)(n->value);
    auto vum=(Viewer_UI_Mesh*)(vs->evolution);
    vum->Data_rows=4;
    vum->Data_index_rows=2;
    vum->color_rows=vum->Data_rows;
    vum->Data=(float*)malloc(sizeof(float)*3*vum->Data_rows);
    vum->Data_index=(unsigned int*)malloc(sizeof(unsigned int)*4*vum->Data_index_rows);
    memmove(vum->Data,pos,sizeof(float)*vum->Data_rows*3);
    vum->Data_index[0]=3;vum->Data_index[1]=0;vum->Data_index[2]=1;vum->Data_index[3]=3;
    vum->Data_index[4]=3;vum->Data_index[5]=1;vum->Data_index[6]=2;vum->Data_index[7]=3;

    free_node(n);
    char texture[]="Texture";
    n=vw->create_something(vw,texture);
    vs=(Viewer_Something*)(n->value);
    free_node(node_reverse(n));
    Viewer_Texture*vt=(Viewer_Texture*)(vs->evolution);
    vum->texture=vs;
    vt->image_file=(char*)malloc(sizeof(char)*20);
    strcpy(vt->image_file,image);
    float *texcoords1=(float*)malloc(sizeof(float)*vum->Data_index_rows*7);
    texcoords1[0]=3;
    texcoords1[1]=0.0;texcoords1[2]=0.0;
    texcoords1[3]=1.0;texcoords1[4]=0.0;
    texcoords1[5]=0.0;texcoords1[6]=1.0;
    texcoords1[7]=3;
    texcoords1[8]=1.0;texcoords1[9]=0.0;
    texcoords1[10]=1.0;texcoords1[11]=1.0;
    texcoords1[12]=0.0;texcoords1[13]=1.0;
    vt->each_face_texture_coord=texcoords1;  

    n=vw->create_something(vw,"Intera");
    vs=(Viewer_Something*)(n->value);
    auto vi=(Viewer_Intera*)(vs->evolution);
    vi->representation=vum;
    vi->mouse_button_callback=call_fun;
    vi->prop=prop;
    free_node(n);
}

char* test2()
{
    nfdchar_t *outPath = NULL;
    nfdresult_t result=NFD_PickFolder( NULL,&outPath);

    //nfdresult_t result = NFD_OpenDialog( NULL, NULL, &outPath ); 
    if ( result == NFD_OKAY ) {
        puts("Success!");
       // puts(outPath);
        //free(outPath);
        printf("%s\n",outPath);

        return outPath;
    }
    else if ( result == NFD_CANCEL ) {
        //puts("User pressed cancel.");
    }
    else {
        printf("Error: %s\n", NFD_GetError() );
    }
    return outPath;
}

void test1()
{
    Mesh mesh;
    Mesh_init(&mesh);
    _ReadPly_(&mesh,"bunny.ply");
    Viewer_World_Manager vwm;
    viewer_world_manager_init(&vwm);
    Viewer_World *vw=vwm.create_world(&vwm,NULL);

    add_default_somethings(vw);
    // Node*n=vw->create_something(vw,"Texts");
    // auto vs=(Viewer_Something*)(n->value);
    // Viewer_Texts* vtexts=(Viewer_Texts*)(vs->evolution);
    // vtexts->str=(wchar_t*)malloc(sizeof(wchar_t)*80);
    // memset(vtexts->str,0,sizeof(wchar_t)*80);
    // wcscpy(vtexts->str,L"nihaodsgdooasuytwmqniz");

    // int len=wcslen(vtexts->str);
    // vtexts->text_alpha=(float*)malloc(sizeof(float)*len);
    // memset(vtexts->text_alpha,0,sizeof(float)*len);
    // vtexts->xy[0]=-0.6;vtexts->xy[1]=0.4;vtexts->scale=1.3;
    // free_node(n);
    SFM_struct* sfm_s=(SFM_struct*)malloc(sizeof(SFM_struct));
    sfm_strutct_init(sfm_s);
    sfm_s->vw=vw;

    // _ReadPly_(sfm_s->mesh,"./out/dense.ply");
    // printf("num_v:%d\n",sfm_s->mesh->num_v(sfm_s->mesh));
    
    //test_show_mesh_points(vw,&mesh); 


    float pos_1[12]={-0.6,0.6,1.0,
        -0.3,0.6,1.0,
        -0.3,0.8,1.0,
        -0.6,0.8,1.0
    };
    viewer_add_button(vw,"out_put_dir.jpg",pos_1,select_out_dir_call_fun,sfm_s);


    float pos0[12]={-1.0,0.6,1.0,
        -0.7,0.6,1.0,
        -0.7,0.8,1.0,
        -1.0,0.8,1.0
    };
    viewer_add_button(vw,"select_image.jpg",pos0,select_image_call_fun,sfm_s);

     
    float pos1[12]={-1.0,0.3,1.0,
        -0.7,0.3,1.0,
        -0.7,0.5,1.0,
        -1.0,0.5,1.0
    };
    viewer_add_button(vw,"compute_fe.jpg",pos1,compute_feature_call_fun,sfm_s);
    float pos[12]={-1.0,0.0,1.0,
        -0.7,0.0,1.0,
        -0.7,0.2,1.0,
        -1.0,0.2,1.0
    };
     float pos2[12]={-1.0,-0.3,1.0,
        -0.7,-0.3,1.0,
        -0.7,-0.1,1.0,
        -1.0,-0.1,1.0
    };

    viewer_add_button(vw,"sfm_compute.jpg",pos2 ,compute_sfm_call_fun,sfm_s);
    viewer_add_button(vw,"compute_ma.jpg",pos ,compute_match_call_fun,sfm_s);
    float pos3[12]={-1.0,-0.6,1.0,
        -0.7,-0.6,1.0,
        -0.7,-0.4,1.0,
        -1.0,-0.4,1.0
    };
    viewer_add_button(vw,"compute_densify_cloud.jpg",pos3 ,compute_densify_cloud_call_fun,sfm_s);

    float pos4[12]={-1.0,-0.9,1.0,
        -0.7,-0.9,1.0,
        -0.7,-0.7,1.0,
        -1.0,-0.7,1.0
    };
    viewer_add_button(vw,"point2mesh.jpg",pos4 ,compute_point2mesh_call_fun,sfm_s);


    Node* n=vw->create_something(vw,"Intera");
    auto vs=(Viewer_Something*)(n->value);
    auto vi=(Viewer_Intera*)(vs->evolution);
    vi->key_callback=compute_point2mesh_key_call_fun;
    //vi->mouse_button_callback=call_fun;
     vi->prop=sfm_s;
    free_node(n); 
    printf("num v:%d\n",mesh.num_v(&mesh));
//compute_point2mesh_key_call_fun
    // test_show_mesh_points(vw,&mesh); 
    // test_show_mesh_points(vw, sfm_s->mesh); 

    vw->print_self(vw);
 
    Viewer_Opengl_Interpreter voi;
    sfm_s->voi=&voi;
    viewer_opengl_interpreter_initn(&voi,&vwm);
    voi.interpreter(&voi);
    viewer_opengl_interpreter_free(&voi);
    viewer_world_manager_free(&vwm);
    Mesh_free(&mesh); 
}



int main()
{
    //test2();



    test1();

    printf("end\n");
    return 0; 
}